package net.lulihu.pangolin.headless.common.properties;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置文件 属性解析
 */
public class ConfigProperties {

    private static final Map<String, ConfigProperties> instances = new ConcurrentHashMap<>();

    private Properties configuration = new Properties();

    /**
     * 获取默认配置
     */
    public static ConfigProperties getDefault() {
        return getInstance("config.properties");
    }

    private ConfigProperties(String configFile) {
        initConfig(configFile);
    }

    private ConfigProperties(File file) {
        initConfig(file);
    }

    /**
     * 初始化配置
     */
    private void initConfig(File file) {
        try (InputStream inputStream = new FileInputStream(file)) {
            initConfig(inputStream);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 初始化配置
     *
     * @param configFile 配置文件地址
     */
    private void initConfig(String configFile) {
        try (InputStream inputStream =
                     Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(configFile),
                             "配置文件不存在...")) {
            initConfig(inputStream);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 初始化配置
     */
    private void initConfig(InputStream inputStream) throws IOException {
        try (InputStreamReader reader = new InputStreamReader(inputStream, Charset.forName("GBK"))) {
            configuration.load(reader);
        }
    }

    /**
     * 自定义文件解析**.property
     *
     * @param file 配置文件
     */
    public static ConfigProperties getInstance(File file) {
        return instances.computeIfAbsent(file.getPath(), k -> new ConfigProperties(file));
    }

    /**
     * 自定义文件解析**.property
     * <p>
     * 注意该方法只解析jar包内的文件地址
     *
     * @param configFile 配置文件地址
     */
    public static ConfigProperties getInstance(String configFile) {
        return instances.computeIfAbsent(configFile, ConfigProperties::new);
    }

    public String getStringValue(String key, String defaultValue) {
        String value = getProperty(key);
        return value == null ? defaultValue : value;
    }

    public String getStringValue(String key) {
        String value = getProperty(key);
        if (value != null) return value;
        throw new NullPointerException("[" + key + "]不存在指定键的值...");
    }

    public Integer getIntValue(String key, int defaultValue) {
        return LangUtil.parseInt(getProperty(key), defaultValue);
    }

    public Integer getIntValue(String key) {
        String property = getStringValue(key);
        return Integer.valueOf(property);
    }

    public Double getDoubleValue(String key) {
        String property = getStringValue(key);
        return Double.valueOf(property);
    }

    public Double getDoubleValue(String key, Double defaultValue) {
        return LangUtil.parseDouble(getProperty(key), defaultValue);
    }

    public Long getLongValue(String key) {
        String property = getStringValue(key);
        return Long.valueOf(property);
    }

    public Long getLongValue(String key, Long defaultValue) {
        return LangUtil.parseLong(getProperty(key), defaultValue);
    }

    public Boolean getBooleanValue(String key) {
        String property = getStringValue(key);
        return Boolean.valueOf(property);
    }

    public Boolean getBooleanValue(String key, Boolean defaultValue) {
        return LangUtil.parseBoolean(getProperty(key), defaultValue);
    }

    /**
     * 获取配置属性
     *
     * @param key 键
     * @return UTF-8 编码的字符串
     */
    private String getProperty(String key) {
        return configuration.getProperty(key);
    }

}